package cat.joronya.supermanager.service;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.util.Log;
import cat.joronya.supermanager.DatabaseHelper;
import cat.joronya.supermanager.Supermanager;
import cat.joronya.supermanager.Supermanager.PrivateLeagueTeam;
import cat.joronya.supermanager.privateleague.PrivateLeague;
import cat.joronya.supermanager.team.Team;

/**
 * Recuperem el llistat de private leagues.
 * 
 * @author pol
 */
public class PrivateLeaguesSync extends Object// AsyncTask<String,Void,Integer>
{
	private static final String TAG = "supermanager";

	// el service
	private SupermanagerService service;

	// el client http on fer les peticions
	private DefaultHttpClient client = null;

	// status de retorn
	public int status = -1;

	// private leagues GET
	private static final String PRIVATE_LEAGUES_LIST_GET = InitSync.BASE_URL
			+ "/ligasprivadas.php";
	// private league teams
	private static final String PRIVATE_LEAGUE_TEAMS = InitSync.BASE_URL
			+ "/verprivada.php";

	// dades extretes de les pagines
	public ArrayList<PrivateLeague> privateLeagues;

	/**
	 * Constructor amb el intentService que el crida.
	 * 
	 * @param intentService
	 */
	public PrivateLeaguesSync(SupermanagerService service,
			DefaultHttpClient client) {
		this.service = service;
		this.client = client;
	}
	
	public void sync()
	{
		// parse pages
		parse();
		
		// persist parsing results
		persist();
	}
	
	protected void parse()
	{
		try {
			// checkejem per connectivitat
			ConnectivityManager cm = (ConnectivityManager) service
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			boolean online = cm.getActiveNetworkInfo()
					.isConnectedOrConnecting();

			if (!online)
				throw new ConnectivityException();

			HttpGet plHttpGet = new HttpGet(PRIVATE_LEAGUES_LIST_GET);
			HttpResponse response = client.execute(plHttpGet);
			
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			response.getEntity().writeTo(os);
			String privateLeagueslPage = os.toString(HTTP.ISO_8859_1);
			
			//PrivateLeaguesParser parser = PrivateLeaguesParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.htmlcleanerImpl"));
			PrivateLeaguesParser parser = PrivateLeaguesParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.substrImpl"));
			Log.d(Supermanager.TAG, "Start parsing private leagues page...");
			long elapsedTime = parser.parse(privateLeagueslPage);
			Log.d(Supermanager.TAG, "Stop parsing private leagues page! Elapsed time: "+elapsedTime/1000);

			privateLeagues = parser.getPrivateLeagues();
			
			// de cada private league parsejem el detall point, general i broker
			for (PrivateLeague pl : privateLeagues) {
				getPrivateLeagueTeams(pl);
				getPrivateLeagueTeamsGeneral(pl);
				getPrivateLeagueTeamsBroker(pl);
			}

			// parsejat ok
			status = Supermanager.PRIVATE_LEAGUES_PARSED_OK;
			Log.d(TAG, "PrivateLeaguesSync status: PRIVATE_LEAGUES_PARSED_OK - "+status);
			return;
		} catch (ConnectivityException ce) {
			// error de connectivitat
			status = Supermanager.CONNECTIVITY_ERROR_STATUS;
			Log.d(TAG, "PrivateLeaguesSync status: CONNECTIVITY_ERROR_STATUS - "+status);
			return;
		} catch (Exception e) {
			// altre error, notifiquem i anem offline
			status = Supermanager.OTHER_ERROR_STATUS;
			Log.d(TAG, "PrivateLeaguesSync status: OTHER_ERROR_STATUS - "+status);
			return;
		}
	}

	/**
	 * Parse the verprivada.php per extreure'n els equips de la lliga privada
	 * passada pel que fa a punts.
	 * 
	 * @return true si no hi ha hagut error, altrament false.
	 */
	public boolean getPrivateLeagueTeams(PrivateLeague privateLeague) throws Exception 
	{
		HttpGet ltHttpGet = new HttpGet(PRIVATE_LEAGUE_TEAMS + "?id_pri="
				+ privateLeague.getId());
		HttpResponse response = client.execute(ltHttpGet);
		
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		response.getEntity().writeTo(os);
		String leagueTeamsPage = os.toString(HTTP.ISO_8859_1);
		
		//PrivateLeaguesParser parser = PrivateLeaguesParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.htmlcleanerImpl"));
		PrivateLeaguesParser parser = PrivateLeaguesParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.substrImpl"));
		Log.d(Supermanager.TAG, "Start parsing private leagues page jornada...");
		long elapsedTime = parser.parseTeams(leagueTeamsPage, privateLeague);
		Log.d(Supermanager.TAG, "Stop parsing private leagues page jornada! Elapsed time: "+elapsedTime/1000);

		return true;
	}

	/**
	 * Parse the verprivada.php per extreure'n els equips de la lliga privada
	 * passada i la puntuacio general.
	 * 
	 * @return true si no hi ha hagut error, altrament false.
	 */
	public boolean getPrivateLeagueTeamsGeneral(PrivateLeague privateLeague) throws Exception 
	{
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		nvps.add(new BasicNameValuePair("id_pri", privateLeague.getId()));
		nvps.add(new BasicNameValuePair("tipo", "valoracion"));

		HttpPost ltHttpPost = new HttpPost(PRIVATE_LEAGUE_TEAMS);
		ltHttpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.ISO_8859_1));
		HttpResponse response = client.execute(ltHttpPost);

		ByteArrayOutputStream os = new ByteArrayOutputStream();
		response.getEntity().writeTo(os);
		String leagueTeamsPage = os.toString(HTTP.ISO_8859_1);
		
		//PrivateLeaguesParser parser = PrivateLeaguesParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.htmlcleanerImpl"));
		PrivateLeaguesParser parser = PrivateLeaguesParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.substrImpl"));
		Log.d(Supermanager.TAG, "Start parsing private leagues page general...");
		long elapsedTime = parser.parseGeneralTeams(leagueTeamsPage, privateLeague);
		Log.d(Supermanager.TAG, "Stop parsing private leagues page general! Elapsed time: "+elapsedTime/1000);

		return true;
	}

	/**
	 * Parse the verprivada.php per extreure'n els equips de la lliga privada
	 * passada i la puntuacio boker.
	 * 
	 * @return true si no hi ha hagut error, altrament false.
	 */
	public boolean getPrivateLeagueTeamsBroker(PrivateLeague privateLeague) throws Exception 
	{
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		nvps.add(new BasicNameValuePair("id_pri", privateLeague.getId()));
		nvps.add(new BasicNameValuePair("tipo", "broker"));

		HttpPost ltHttpPost = new HttpPost(PRIVATE_LEAGUE_TEAMS);
		ltHttpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.ISO_8859_1));
		HttpResponse response = client.execute(ltHttpPost);
		
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		response.getEntity().writeTo(os);
		String leagueTeamsPage = os.toString(HTTP.ISO_8859_1);
		
		//PrivateLeaguesParser parser = PrivateLeaguesParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.htmlcleanerImpl"));
		PrivateLeaguesParser parser = PrivateLeaguesParserProvider.getImpl(Package.getPackage("cat.joronya.supermanager.service.substrImpl"));
		Log.d(Supermanager.TAG, "Start parsing private leagues page general...");
		long elapsedTime = parser.parseBrokerTeams(leagueTeamsPage, privateLeague);
		Log.d(Supermanager.TAG, "Stop parsing private leagues page general! Elapsed time: "+elapsedTime/1000);

        return true;
	}

	/**
	 * Guardar les dades trobades a DB.
	 */
	protected void persist() 
	{
		// tractem cada lliga privada
		Log.d(TAG, "Parsed " + privateLeagues.size()
				+ " private leagues, going to insert/update");
		for (PrivateLeague pl : privateLeagues)
		{
			// insert or update la private league
			String lastPathSegment = insertOrUpdatePrivateLeague(Supermanager.PrivateLeague.CONTENT_URI, pl);
			
			// lliga sense equips inscrits
			if (pl.getTeams() == null) {
				Log.d(TAG, "Private leagues [" + pl.getName() + "] has no teams");
				continue;
			}

			// insertem els equips de la lliga privada
			for (Team team : pl.getTeams().values()) 
			{
				insertOrUpdatePrivateLeagueTeam(lastPathSegment, pl, team);
			}
		}
	}
	
	/**
	 * Insert or Update PrivateLeague as needed.
	 * @param uri
	 * @param pl
	 * @return
	 */
	private String insertOrUpdatePrivateLeague(Uri uri, PrivateLeague pl)
	{
		// insertem la lliga privada
		ContentValues values = new ContentValues();
		values.put(Supermanager.PrivateLeague.NAME, pl.getName());
		values.put(Supermanager.PrivateLeague.NUMBER_OF_TEAMS,
				pl.getNumberOfTeams());
		values.put(Supermanager.PrivateLeague.ID_PRIV, pl.getId());
		
		Uri plUri = Supermanager.PrivateLeague.CONTENT_URI;
		String lastPathSegment = "0";
		
		// si update no retorna 1 reg, llavors insert
		if( service.getContentResolver().update(uri, 
				values, 
				Supermanager.PrivateLeague.ID_PRIV+" = ? ", 
				new String[]{pl.getId()}) == 0 )
		{
			plUri = service.getContentResolver().insert(uri, values);
			lastPathSegment = plUri.getLastPathSegment();
			Log.d(TAG, "Inserting private league [" + pl.getName()
					+ "] with Uri [" + plUri + "] lastPathSegment ["
					+ lastPathSegment + "]");
		}
		else
		{
			Cursor cursor = service.getContentResolver().
				query(Supermanager.PrivateLeague.CONTENT_URI, 
					  Supermanager.PrivateLeague.PROJECTION, 
					  Supermanager.PrivateLeague.ID_PRIV+" = ? ", 
					  new String[]{pl.getId()}, 
					  Supermanager.PrivateLeague.DEFAULT_SORT_ORDER);
			
			if( cursor.moveToFirst() )
			{
				lastPathSegment = ""+cursor.getLong(0);
				plUri = ContentUris.withAppendedId(Supermanager.PrivateLeague.CONTENT_URI, cursor.getLong(0));
			}
			Log.d(TAG, "Updating private league [" + pl.getName()
					+ "] with Uri [" + plUri + "] lastPathSegment ["
					+ lastPathSegment + "]");
		}
		
		return lastPathSegment;
	}
	
	private Uri insertOrUpdatePrivateLeagueTeam(String lastPathSegment, PrivateLeague pl, Team team)
	{
		// insertem l'equip
		ContentValues teamValues = new ContentValues();
		teamValues.put(Supermanager.PrivateLeagueTeam._PRIVATE_LEAGUE_ID, lastPathSegment);
		teamValues.put(Supermanager.PrivateLeagueTeam.NAME, team.getName());
		teamValues.put(Supermanager.PrivateLeagueTeam.DAY, team.getDay());
		teamValues.put(Supermanager.PrivateLeagueTeam.MANAGER, team.getManager());
		teamValues.put(Supermanager.PrivateLeagueTeam.CITY, team.getCity());
		teamValues.put(Supermanager.PrivateLeagueTeam.ID_PRIV, pl.getId());
		teamValues.put(Supermanager.PrivateLeagueTeam.POINTS, team.getPoints());
		teamValues.put(Supermanager.PrivateLeagueTeam.GENERAL, team.getGeneral());
		teamValues.put(Supermanager.PrivateLeagueTeam.BROKER, team.getBroker());
		
		Uri tUri = Supermanager.PrivateLeagueTeam.CONTENT_URI;
		// si update no retorna 1 reg, llavors insert
		if( service.getContentResolver().update(Supermanager.PrivateLeagueTeam.CONTENT_URI, 
				teamValues, 
				Supermanager.PrivateLeagueTeam.ID_PRIV+" = ? AND "+
				Supermanager.PrivateLeagueTeam.NAME+" = ? AND "+
				Supermanager.PrivateLeagueTeam.DAY+" = ? ", 
				new String[]{pl.getId(), team.getName(), team.getDay().toString()}) == 0 )
		{
			tUri = service.getContentResolver().insert(
					PrivateLeagueTeam.CONTENT_URI, teamValues);
			Log.d(TAG, "Inserting private league team [" + team.getName() + "] of league ["
					+ pl.getName() + "] with Uri [" + tUri + "]");
		}
		else
		{
			Cursor cursor = service.getContentResolver().
			query(Supermanager.PrivateLeagueTeam.CONTENT_URI, 
				  Supermanager.PrivateLeagueTeam.PROJECTION, 
				  DatabaseHelper.PRIVATE_LEAGUE_TEAM_TABLE_NAME+"."+Supermanager.PrivateLeagueTeam.ID_PRIV+" = ? AND "+
				  DatabaseHelper.PRIVATE_LEAGUE_TEAM_TABLE_NAME+"."+Supermanager.PrivateLeagueTeam.NAME+" = ? AND "+
				  DatabaseHelper.PRIVATE_LEAGUE_TEAM_TABLE_NAME+"."+Supermanager.PrivateLeagueTeam.DAY+" = ? ", 
				  new String[]{pl.getId(), team.getName(), team.getDay().toString()}, 
				  Supermanager.PrivateLeagueTeam.DEFAULT_SORT_ORDER);
		
			if( cursor.moveToFirst() )
			{
				tUri = ContentUris.withAppendedId(Supermanager.PrivateLeagueTeam.CONTENT_URI, cursor.getLong(0));
		
				Log.d(TAG, "Updating private league team [" + team.getName() + "] of league ["
						+ pl.getName() + "] with Uri [" + tUri + "]");
			}
		}
		
		return tUri;
	}
}
